package com.sun.config;

import com.sun.springsecurity.service.impl.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

/**
 * @Description: Security的配置类
 * @Author hugh.sun
 * @Date 2021/12/4 13:21
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
/*WebSecurityConfigurerAdapter整个springSecurity中最重要的一个类*/
    /*自定义的异常处理*/
    @Autowired
    private MyAccessDeniedHandler accessDeniedHandler;
    @Autowired
    private UserServiceImpl service;
    @Autowired
    private DataSource dataSource;
    @Autowired
    private PersistentTokenRepository tokenRepository;


    /*自定义登录页面   alt+insert可以实现类中的方法*/
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()
                /*自定义登录页面*/
                .loginPage("/login.html")
                /*自定义登录逻辑*/
                .loginProcessingUrl("/login")
                /*登录成功之后的跳转页面必须是post方式*/
                .successForwardUrl("/toMain")

                /*如果你不想通过post跳转也很简单你需要自己定义一个*/
             /* .successHandler(new MyAuthenticationSuccessHandler("/main1.html"))*/


                /*登录失败之后的跳转页面同样必须事post方式*/
                .failureForwardUrl("/toError")
                /*自定义用户名密码的参数     !!!一定要和登录的用户名密码参数匹配不然找不到*/
                .usernameParameter("username")
                .passwordParameter("password");


                /*url匹配规则
                * ?：匹配一个字符
                * *：匹配0或多个字符
                * **：匹配0个或者多个目录
                * */
        /*所有的请求都要经过授权之后才可以用*/
        http.authorizeRequests()
                /*放行登录页面*/
                .antMatchers("/login.html").permitAll()
                .antMatchers("/error.html").permitAll()
                /*访问image下面的所有资源*/
                /*.antMatchers("/image/**").permitAll()*/
                /*如果你有admin这个角色的权限就放放行你   hasAuthority严格区分大小写*/
                /*.antMatchers("/main1.html").hasAuthority("admin")*/
                /*可以匹配多个权限*/
               /* .antMatchers("/main1.html").hasAnyAuthority("admin","admiN")*/
                /*根据角色匹配  不能以ROLE_开口   严格区分大消息*/
               // .antMatchers("/main1.html").hasRole("abc")
                /*匹配多个角色*/
               .antMatchers("/main1.html").hasAnyRole("abc","adC")
                /*限制只能允许127.0.0.1访问*/
               // .antMatchers("/main1.html").hasIpAddress("127.0.0.1")

                //.antMatchers("/**/*.jpg").permitAll()
                /*所有请求都需要验证，一般放在最后一行， */
                .anyRequest().authenticated();
                /*根据当前的uri需要什么角色*/
                /*.anyRequest().access("@myServiceImpl.hasPermission(request,authentication)");*/
        /*异常处理*/
        http.exceptionHandling()
                        .accessDeniedHandler(accessDeniedHandler);
        /*默认失效时间为两周*/
        http.rememberMe()
                //自定义失效时间
                //.tokenValiditySeconds()
                //自定义登录逻辑
                        .userDetailsService(service)
                //指定存储位置，看是用jdbc存储，还是内存，一般选择jdbc
                                .tokenRepository(tokenRepository);
        //退出登录
        http.logout()
                .logoutUrl("/logout")
                        .logoutSuccessUrl("/login.html");

        http.csrf().disable();

    }

    @Bean
    public PasswordEncoder pw(){
        return new BCryptPasswordEncoder();
    }

    @Bean
    public PersistentTokenRepository tokenRepository(){
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        //设置数据源
        tokenRepository.setDataSource(dataSource);
        //启动的时候是否生成表  第一次要，之后要注释掉
        //tokenRepository.setCreateTableOnStartup(true);
        return tokenRepository;
    }

}
